package com.vegetable.common.utils;

import com.vegetable.modules.entity.baseData.BankCard;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class BankCardRedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // Redis中存储bankNo的set的key
    private static final String BANK_NO_SET_KEY = "bank_card:bank_no_set";
    
    // Redis中存储bankNo到bankCard信息的hash的key
    private static final String BANK_NO_BANK_CARD_HASH_KEY = "bank_card:bank_no_map";
    
    // Redis中存储addressBookId到bankNo集合的set的key
    private static final String ADDRESS_BOOK_ID_BANK_NOS_SET_KEY = "bank_card:address_book_id:";
    
    // Redis中存储前缀索引的key前缀
    private static final String BANK_NO_PREFIX_KEY = "bank_card:bank_no_prefix:";
    
    // Redis中存储后缀索引的key前缀
    private static final String BANK_NO_SUFFIX_KEY = "bank_card:bank_no_suffix:";

    /**
     * 将bankCard列表信息存入Redis缓存
     * @param bankCardList bankCard列表
     */
    public void cacheBankCardList(List<BankCard> bankCardList) {
        if (CollectionUtils.isEmpty(bankCardList)) {
            return;
        }

        // 清空原有的缓存
        redisTemplate.delete(BANK_NO_SET_KEY);
        redisTemplate.delete(BANK_NO_BANK_CARD_HASH_KEY);
        
        // 删除所有前缀和后缀索引
        Set<String> keys = redisTemplate.keys(BANK_NO_PREFIX_KEY + "*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
        
        keys = redisTemplate.keys(BANK_NO_SUFFIX_KEY + "*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
        
        // 删除所有addressBookId相关的缓存
        keys = redisTemplate.keys(ADDRESS_BOOK_ID_BANK_NOS_SET_KEY + "*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
        
        // 存储bankNo到bankCard的映射
        for (BankCard bankCard : bankCardList) {
            // 只缓存启用状态的银行卡
            if (bankCard.getStatus() != null && bankCard.getStatus() == 1 && 
                bankCard.getIsDel() != null && bankCard.getIsDel() == 0) {
                String bankNo = bankCard.getBankNo();
                if (bankNo != null && !bankNo.isEmpty()) {
                    // 将bankNo添加到set中，用于快速判断是否存在
                    redisTemplate.opsForSet().add(BANK_NO_SET_KEY, bankNo);
                    
                    // 将bankNo和bankCard信息存入hash中，用于快速获取bankCard信息
                    redisTemplate.opsForHash().put(BANK_NO_BANK_CARD_HASH_KEY, bankNo, bankCard);
                    
                    // 将bankNo添加到addressBookId集合中
                    String addressBookIdKey = ADDRESS_BOOK_ID_BANK_NOS_SET_KEY + bankCard.getAddressBookId();
                    redisTemplate.opsForSet().add(addressBookIdKey, bankNo);
                    
                    // 创建前缀和后缀索引用于模糊匹配
                    createPrefixAndSuffixIndex(bankNo);
                }
            }
        }
    }

    /**
     * 根据addressBookId获取其所有银行卡号
     * @param addressBookId 通讯录ID
     * @return 银行卡号集合
     */
    public Set<String> getBankNosByAddressBookId(Long addressBookId) {
        String key = ADDRESS_BOOK_ID_BANK_NOS_SET_KEY + addressBookId;
        Set<Object> members = redisTemplate.opsForSet().members(key);
        Set<String> result = new HashSet<>();
        if (members != null) {
            for (Object obj : members) {
                if (obj instanceof String) {
                    result.add((String) obj);
                }
            }
        }
        return result;
    }

    /**
     * 创建前缀和后缀索引用于模糊匹配
     * @param bankNo 银行卡号
     */
    private void createPrefixAndSuffixIndex(String bankNo) {
        // 创建前缀索引（最多前6位）
        for (int i = 1; i <= Math.min(6, bankNo.length()); i++) {
            String prefix = bankNo.substring(0, i);
            String prefixKey = BANK_NO_PREFIX_KEY + prefix;
            redisTemplate.opsForSet().add(prefixKey, bankNo);
        }
        
        // 创建后缀索引（最多后6位）
        for (int i = 0; i < Math.min(6, bankNo.length()); i++) {
            String suffix = bankNo.substring(bankNo.length() - i - 1);
            String suffixKey = BANK_NO_SUFFIX_KEY + suffix;
            redisTemplate.opsForSet().add(suffixKey, bankNo);
        }
    }

    /**
     * 判断bankNo是否存在（支持模糊匹配）
     * @param bankNo 银行卡号，可能包含*
     * @return 是否存在
     */
    public boolean isBankNoExists(String bankNo) {
        if (bankNo == null || bankNo.isEmpty()) {
            return false;
        }

        // 如果包含*，则进行模糊匹配
        if (bankNo.contains("*")) {
            Set<String> matchingBankNos = findMatchingBankNos(bankNo);
            return !matchingBankNos.isEmpty();
        } else {
            // 精确匹配
            return redisTemplate.opsForSet().isMember(BANK_NO_SET_KEY, bankNo);
        }
    }

    /**
     * 根据bankNo获取bankCard信息
     * @param bankNo 银行卡号
     * @return bankCard信息
     */
    public BankCard getBankCardByBankNo(String bankNo) {
        if (bankNo == null || bankNo.isEmpty()) {
            return null;
        }
        return (BankCard) redisTemplate.opsForHash().get(BANK_NO_BANK_CARD_HASH_KEY, bankNo);
    }

    /**
     * 根据模糊bankNo获取所有匹配的bankNo列表
     * @param fuzzyBankNo 模糊银行卡号，包含*
     * @return 匹配的bankNo列表
     */
    public Set<String> getMatchingBankNos(String fuzzyBankNo) {
        return findMatchingBankNos(fuzzyBankNo);
    }
    
    /**
     * 根据模糊bankNo模式查找匹配的BankCard列表
     * @param fuzzyBankNo 模糊银行卡号，包含*
     * @return 匹配的BankCard列表
     */
    public Set<BankCard> getMatchingBankCards(String fuzzyBankNo) {
        Set<BankCard> result = new HashSet<>();
        Set<String> matchingBankNos = findMatchingBankNos(fuzzyBankNo);
        
        if (!CollectionUtils.isEmpty(matchingBankNos)) {
            for (String bankNo : matchingBankNos) {
                BankCard bankCard = getBankCardByBankNo(bankNo);
                if (bankCard != null) {
                    result.add(bankCard);
                }
            }
        }
        
        return result;
    }
    
    /**
     * 根据模糊模式查找匹配的bankNo
     * @param pattern 模糊模式，*代表任意字符
     * @return 匹配的bankNo集合
     */
    private Set<String> findMatchingBankNos(String pattern) {
        if (pattern == null || pattern.isEmpty()) {
            return new HashSet<>();
        }
        
        // 如果没有*，直接精确查找
        if (!pattern.contains("*")) {
            Boolean exists = redisTemplate.opsForSet().isMember(BANK_NO_SET_KEY, pattern);
            Set<String> result = new HashSet<>();
            if (exists != null && exists) {
                result.add(pattern);
            }
            return result;
        }
        
        // 处理包含*的情况
        String[] parts = pattern.split("\\*", -1); // -1参数保留空字符串
        
        // 如果只有一个部分且为空，说明是全匹配
        if (parts.length == 1 && parts[0].isEmpty()) {
            Set<Object> members = redisTemplate.opsForSet().members(BANK_NO_SET_KEY);
            Set<String> result = new HashSet<>();
            if (members != null) {
                for (Object obj : members) {
                    if (obj instanceof String) {
                        result.add((String) obj);
                    }
                }
            }
            return result;
        }
        
        Set<String> result = new HashSet<>();
        
        // 如果第一个部分不为空，使用前缀匹配
        if (!parts[0].isEmpty()) {
            String prefixKey = BANK_NO_PREFIX_KEY + parts[0];
            Set<Object> members = redisTemplate.opsForSet().members(prefixKey);
            if (members == null || members.isEmpty()) {
                return result;
            }
            for (Object obj : members) {
                if (obj instanceof String) {
                    result.add((String) obj);
                }
            }
        } else {
            // 如果第一个部分为空，初始化为所有bankNo
            Set<Object> members = redisTemplate.opsForSet().members(BANK_NO_SET_KEY);
            if (members != null) {
                for (Object obj : members) {
                    if (obj instanceof String) {
                        result.add((String) obj);
                    }
                }
            }
        }
        
        // 如果最后一个部分不为空，使用后缀匹配
        if (parts.length > 0 && !parts[parts.length - 1].isEmpty()) {
            String suffixKey = BANK_NO_SUFFIX_KEY + parts[parts.length - 1];
            Set<Object> members = redisTemplate.opsForSet().members(suffixKey);
            Set<String> suffixMatches = new HashSet<>();
            if (members != null) {
                for (Object obj : members) {
                    if (obj instanceof String) {
                        suffixMatches.add((String) obj);
                    }
                }
            }
            
            // 取交集
            if (!result.isEmpty()) {
                result.retainAll(suffixMatches);
            } else {
                result.addAll(suffixMatches);
            }
        }
        
        // 如果有中间部分且不为空，需要进一步过滤
        if (parts.length > 2) {
            for (int i = 1; i < parts.length - 1; i++) {
                if (!parts[i].isEmpty()) {
                    String middlePart = parts[i];
                    result = result.stream()
                            .filter(bankNo -> bankNo.contains(middlePart))
                            .collect(java.util.stream.Collectors.toSet());
                }
            }
        }
        
        return result;
    }
}